package com.example.haedataupdate.service;

import com.example.haedataupdate.dao.TestDomainDao;
import com.example.haedataupdate.domain.TestDomainDo;
import com.example.haedataupdate.domain.TestDomainDto;
import com.google.common.collect.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: yuanjianpeng5
 * @createdate: 2020-05-09 15:28
 * @lastdate:
 */
@Service
public class DataUpdateImp implements DataUpdateService {

    @Autowired
    private TestDomainDao testDomainDao;

    @Override
    public void initHandler(List<TestDomainDto> testDomainDtoList) {
        List<TestDomainDo> insertDataList = new ArrayList<>();
        testDomainDtoList.stream().forEach(testDomainDto -> {
            TestDomainDo testDomainDo = new TestDomainDo();
            BeanUtils.copyProperties(testDomainDto, testDomainDo);
            insertDataList.add(testDomainDo);
        });
        testDomainDao.batchInsert(insertDataList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void traditionUpdateHandler(List<TestDomainDto> testDomainDtoList) {
        // 删除已不需要的数据
        List<TestDomainDo> alreadyDataList = testDomainDao.selectAll();
        for (TestDomainDo testDomainDo : alreadyDataList) {
            boolean isDelete = true;
           // 若待更新列表中有该数据则保留
            for (TestDomainDto testDomainDto : testDomainDtoList) {
                if (testDomainDto.getCode().equals(testDomainDo.getCode())) {
                    isDelete = false;
                    break;
                }
            }
            if (isDelete) {
                testDomainDao.deleteById(testDomainDo.getId());
            }
        }

        // 遍历待更新的数据列表
        for (TestDomainDto testDomainDto : testDomainDtoList) {
            TestDomainDo testDomainDo = testDomainDao.selectByCode(testDomainDto.getCode());
            if (null != testDomainDo) {
                // 库中已存在则更新
                testDomainDo.setName(testDomainDto.getName());
                testDomainDao.updateById(testDomainDo);
            } else {
                // 库中不存在则新增
                testDomainDo = new TestDomainDo();
                testDomainDo.setCode(testDomainDto.getCode());
                testDomainDo.setName(testDomainDto.getName());
                testDomainDao.insert(testDomainDo);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void redifineUpdateHandler(List<TestDomainDto> testDomainDoList) {

        // 待更新的数据列表转成“唯一键——数据”映射表
        Map<String, TestDomainDto> readyChangeDataMap = testDomainDoList.stream().collect(Collectors.toMap(TestDomainDto::getCode, obj -> obj, (k1, k2) -> k1));

        // 库中已有记录转成“唯一键——数据”映射表
        List<TestDomainDo> alreadyDataList = testDomainDao.selectAll();
        Map<String, TestDomainDo> alreadyDataMap = alreadyDataList.stream().collect(Collectors.toMap(TestDomainDo::getCode, obj -> obj, (k1, k2) -> k1));

        List<TestDomainDo> insertDataList = new ArrayList<>();
        List<TestDomainDo> updateDataList = new ArrayList<>();
        Map<String, Integer> updateDataKeyMap = new HashMap<>();
        List<Integer> deleteIdList = new ArrayList<>();

        for (Map.Entry<String, TestDomainDto> entry : readyChangeDataMap.entrySet()) {
            TestDomainDo data;
            if (null != alreadyDataMap.get(entry.getKey())) {
                // 将该数据放入待更新数据list列表
                data = alreadyDataMap.get(entry.getKey());
                data.setName(entry.getValue().getName());
                updateDataList.add(data);

                // 将key放入待更新键值映射表
                updateDataKeyMap.put(entry.getKey(), 1);
            } else {
                // 将该数据放入待插入数据list列表
                data = new TestDomainDo();
                data.setCode(entry.getValue().getCode());
                data.setName(entry.getValue().getName());
                insertDataList.add(data);
            }
        }

        // 在待更新键值映射表中遍历已存在数据找出应删除的数据id
        for (Map.Entry<String, TestDomainDo> entry : alreadyDataMap.entrySet()) {
            if (null == updateDataKeyMap.get(entry.getKey())) {
                deleteIdList.add(entry.getValue().getId());
            }
        }

        //批量新增
        testDomainDao.batchInsert(insertDataList);

        //并行更新
        updateDataList.parallelStream().forEach(e -> testDomainDao.updateById(e));

        //批量删除
        testDomainDao.deleteByIdList(deleteIdList);
    }
}